﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Linq;
using System.Text;
using Dry.DbInterpreter;
using System.IO;
using Microsoft.Practices.EnterpriseLibrary.Data;

namespace Dry.Generators
{
    public class BLLGenerator : GeneratorBase
    {
        private static string _namespace;
        private static bool _generateDryLog;
        private static string _tablePrefix;
        private static bool _generateInnerJoinCode;

        public static GeneratorFeedback CreateFile(string strTableName, bool localization)
        {
            return CreateFile(strTableName, localization, "tbl", false);
        }

        public static GeneratorFeedback CreateFile(string strTableName, bool generateDryLog, string tablePrefix, bool generateInnerJoinCode)
        {
            GeneratorFeedback generatorFeedback = new GeneratorFeedback();

            _generateDryLog = generateDryLog;
            _tablePrefix = tablePrefix;
            _generateInnerJoinCode = generateInnerJoinCode;

            string strCode = GetBLLClass(strTableName);
            generatorFeedback.Exception = CreateFileFromString("BLL\\AutoGenerated\\" + strTableName.Substring(tablePrefix.Length, strTableName.Length - tablePrefix.Length) + "BLL.cs", strCode);
            generatorFeedback.Lines = CountLinesInString(strCode);

            return generatorFeedback;
        }

        public static void CreateBaseBLL()
        {
            string strCode = Templates.BaseBLL.GetBaseBLL().Replace("¤ProjectName¤", Dry.ProjectName);
            CreateFileFromString("BLL\\BaseBLL.cs", strCode);
        }

        public static string GetBLLClass(string strTableName)
        {
            Database db = GetDatabase();
            DbCommand dbCommand;
            DataSet dataSet;

            string strCode = String.Empty;
            DbTable dbTable = new DbTable(strTableName, _tablePrefix);

            strCode += GetFileHeader(Dry.ProjectName, "", _generateDryLog.ToString(), "", _tablePrefix, _generateInnerJoinCode.ToString());

            // Add required using statements and namespace
            #region AddBasics

            // Add required using statements
            strCode += "using System;" + _strNewLine;
            strCode += "using System.Collections.Generic;" + _strNewLine;
            strCode += "using System.Data;" + _strNewLine;
            strCode += "using System.Configuration;" + _strNewLine;
            strCode += "using " + Dry.ProjectName + ".DAL;" + _strNewLine;
            strCode += "using " + Dry.ProjectName + ".IP;" + _strNewLine;
            strCode += "using " + Dry.ProjectName + ".BO;" + _strNewLine;
            strCode += _strNewLine;

            // Add the namespace
            strCode += "namespace " + Dry.ProjectName + ".BLL" + _strNewLine;
            strCode += "{" + _strNewLine;

            #endregion

            // Add the class
            strCode += "    public partial class " + dbTable.ClassName + "BLL : BaseBLL" + _strNewLine;
            strCode += "    {" + _strNewLine;
            strCode += "   " + _strNewLine;

            #region AddGetByIdMethods

            // Add TryParseById method
            strCode += "        /// <summary>" + _strNewLine;
            strCode += "        /// Gets a " + dbTable.ClassName + "BO object by its primary key, and returns the first occurence within the database" + _strNewLine;
            strCode += "        /// </summary>" + _strNewLine;
            strCode += "        public static bool TryParseById(int int" + dbTable.ClassName + "Id, out " + dbTable.ClassName + "BO " + dbTable.ObjectName + "BO)" + _strNewLine;
            strCode += "        {" + _strNewLine;
            strCode += "            try {" + _strNewLine;
            strCode += "                " + dbTable.ObjectName + "BO = GetById(int" + dbTable.ClassName + "Id);" + _strNewLine;
            strCode += "                return true;" + _strNewLine;
            strCode += "            } catch {" + _strNewLine;
            strCode += "                " + dbTable.ObjectName + "BO = null;" + _strNewLine;
            strCode += "                return false;" + _strNewLine;
            strCode += "            }" + _strNewLine;
            strCode += "        }" + _strNewLine;
            strCode += "   " + _strNewLine;

            // Add TryGetById method
            strCode += "        /// <summary>" + _strNewLine;
            strCode += "        /// Gets a " + dbTable.ClassName + "BO object by its primary key, and returns the first occurence within the database" + _strNewLine;
            strCode += "        /// </summary>" + _strNewLine;
            strCode += "        public static " + dbTable.ClassName + "BO TryGetById(int int" + dbTable.ClassName + "Id)" + _strNewLine;
            strCode += "        {" + _strNewLine;
            strCode += "            try {" + _strNewLine;
            strCode += "                return GetById(int" + dbTable.ClassName + "Id);" + _strNewLine;
            strCode += "            } catch {" + _strNewLine;
            strCode += "                return null;" + _strNewLine;
            strCode += "            }" + _strNewLine;
            strCode += "        }" + _strNewLine;
            strCode += "   " + _strNewLine;

            // Add GetById method
            strCode += "        /// <summary>" + _strNewLine;
            strCode += "        /// Gets a " + dbTable.ClassName + "BO object by its primary key, and returns the first occurence within the database" + _strNewLine;
            strCode += "        /// </summary>" + _strNewLine;
            strCode += "        public static " + dbTable.ClassName + "BO GetById(int int" + dbTable.ClassName + "Id)" + _strNewLine;
            strCode += "        {" + _strNewLine;
            strCode += "            return " + dbTable.ClassName + "DAL.GetById(int" + dbTable.ClassName + "Id);" + _strNewLine;
            strCode += "        }" + _strNewLine;
            strCode += "   " + _strNewLine;

            #endregion

            #region AddGetByIPMethods

            // Add TryParseByIP method
            strCode += "        /// <summary>" + _strNewLine;
            strCode += "        /// Gets a " + dbTable.ClassName + "BO object by an " + dbTable.ClassName + "IP object, and returns the first occurence within the database" + _strNewLine;
            strCode += "        /// </summary>" + _strNewLine;
            strCode += "        public static bool TryParseByIP(" + dbTable.ClassName + "IP " + dbTable.ObjectName + "IP, out " + dbTable.ClassName + "BO " + dbTable.ObjectName + "BO)" + _strNewLine;
            strCode += "        {" + _strNewLine;
            strCode += "            try {" + _strNewLine;
            strCode += "                " + dbTable.ObjectName + "BO = GetByIP(" + dbTable.ObjectName + "IP);" + _strNewLine;
            strCode += "                return true;" + _strNewLine;
            strCode += "            } catch {" + _strNewLine;
            strCode += "                " + dbTable.ObjectName + "BO = null;" + _strNewLine;
            strCode += "                return false;" + _strNewLine;
            strCode += "            }" + _strNewLine;
            strCode += "        }" + _strNewLine;
            strCode += "   " + _strNewLine;

            // Add TryGetByIP method
            strCode += "        /// <summary>" + _strNewLine;
            strCode += "        /// Gets a " + dbTable.ClassName + "BO object by an " + dbTable.ClassName + "IP object, and returns the first occurence within the database" + _strNewLine;
            strCode += "        /// </summary>" + _strNewLine;
            strCode += "        public static " + dbTable.ClassName + "BO TryGetByIP(" + dbTable.ClassName + "IP " + dbTable.ObjectName + "IP)" + _strNewLine;
            strCode += "        {" + _strNewLine;
            strCode += "            try {" + _strNewLine;
            strCode += "                return GetByIP(" + dbTable.ObjectName + "IP);" + _strNewLine;
            strCode += "            } catch {" + _strNewLine;
            strCode += "                return null;" + _strNewLine;
            strCode += "            }" + _strNewLine;
            strCode += "        }" + _strNewLine;
            strCode += "   " + _strNewLine;

            // Add GetByIP method
            strCode += "        /// <summary>" + _strNewLine;
            strCode += "        /// Gets a " + dbTable.ClassName + "BO object by an " + dbTable.ClassName + "IP object, and returns the first occurence within the database" + _strNewLine;
            strCode += "        /// </summary>" + _strNewLine;
            strCode += "        public static " + dbTable.ClassName + "BO GetByIP(" + dbTable.ClassName + "IP " + dbTable.ObjectName + "IP)" + _strNewLine;
            strCode += "        {" + _strNewLine;
            strCode += "            List<" + dbTable.ClassName + "BO> lst" + dbTable.ClassName + " = GetListByIP(" + dbTable.ObjectName + "IP);" + _strNewLine;
            strCode += "            if(lst" + dbTable.ClassName + ".Count == 1)" + _strNewLine;
            strCode += "                return lst" + dbTable.ClassName + "[0];" + _strNewLine;
            strCode += "            else if(lst" + dbTable.ClassName + ".Count == 0)" + _strNewLine;
            strCode += "                throw new Exception(\"Dry could not find a(n) '" + dbTable.ObjectName + "' with that IP object\");" + _strNewLine;
            strCode += "            else" + _strNewLine;
            strCode += "                throw new Exception(\"Dry founded more than one occurens with this IP object, should only return one\");" + _strNewLine;
            strCode += "        }" + _strNewLine;
            strCode += "   " + _strNewLine;

            #endregion

            // Add CountByIP methods that takes a single IP object
            strCode += "        /// <summary>" + _strNewLine;
            strCode += "        /// Count the number of " + dbTable.ClassName + "BO objects that should be returned by an " + dbTable.ClassName + "IP object." + _strNewLine;
            strCode += "        /// </summary>" + _strNewLine;
            strCode += "        public static Int32 CountByIP(" + dbTable.ClassName + "IP " + dbTable.ObjectName + "IP)" + _strNewLine;
            strCode += "        {" + _strNewLine;
            strCode += "            return " + dbTable.ClassName + "DAL.CountByIP(new List<" + dbTable.ClassName + "IP>() { " + dbTable.ObjectName + "IP });" + _strNewLine;
            strCode += "        }" + _strNewLine;
            strCode += "   " + _strNewLine;

            #region AddGetListByMethods

            // Add GetIdListByIP methods that takes a single IP object
            strCode += "        /// <summary>" + _strNewLine;
            strCode += "        /// Gets a list if integers from the " + dbTable.ClassName + "BO object's primary key by an " + dbTable.ClassName + "IP object." + _strNewLine;
            strCode += "        /// </summary>" + _strNewLine;
            strCode += "        public static List<Int32> GetIdListByIP(" + dbTable.ClassName + "IP " + dbTable.ObjectName + "IP)" + _strNewLine;
            strCode += "        {" + _strNewLine;
            strCode += "            return " + dbTable.ClassName + "DAL.GetIdListByIP(new List<" + dbTable.ClassName + "IP>() { " + dbTable.ObjectName + "IP }, new List<" + dbTable.ClassName + "DAL.SortOrderType>());" + _strNewLine;
            strCode += "        }" + _strNewLine;
            strCode += "   " + _strNewLine;

            strCode += "        /// <summary>" + _strNewLine;
            strCode += "        /// Gets a list if integers from the " + dbTable.ClassName + "BO object's primary key by an " + dbTable.ClassName + "IP object." + _strNewLine;
            strCode += "        /// </summary>" + _strNewLine;
            strCode += "        public static List<Int32> GetIdListByIP(" + dbTable.ClassName + "IP " + dbTable.ObjectName + "IP, " + dbTable.ClassName + "DAL.SortOrderType sortOrder)" + _strNewLine;
            strCode += "        {" + _strNewLine;
            strCode += "            return " + dbTable.ClassName + "DAL.GetIdListByIP(new List<" + dbTable.ClassName + "IP>() { " + dbTable.ObjectName + "IP }, new List<" + dbTable.ClassName + "DAL.SortOrderType>() { sortOrder });" + _strNewLine;
            strCode += "        }" + _strNewLine;
            strCode += "   " + _strNewLine;

            strCode += "        /// <summary>" + _strNewLine;
            strCode += "        /// Gets a list if integers from the " + dbTable.ClassName + "BO object's primary key by an " + dbTable.ClassName + "IP object." + _strNewLine;
            strCode += "        /// </summary>" + _strNewLine;
            strCode += "        public static List<Int32> GetIdListByIP(" + dbTable.ClassName + "IP " + dbTable.ObjectName + "IP, List<" + dbTable.ClassName + "DAL.SortOrderType> lstSortOrders)" + _strNewLine;
            strCode += "        {" + _strNewLine;
            strCode += "            return " + dbTable.ClassName + "DAL.GetIdListByIP(new List<" + dbTable.ClassName + "IP>() { " + dbTable.ObjectName + "IP }, lstSortOrders);" + _strNewLine;
            strCode += "        }" + _strNewLine;
            strCode += "   " + _strNewLine;
            
            // Add TryGetListByIP methods that takes a single IP object
            strCode += "        public static List<" + dbTable.ClassName + "BO> TryGetListByIP(" + dbTable.ClassName + "IP " + dbTable.ObjectName + "IP)" + _strNewLine;
            strCode += "        {" + _strNewLine;
            strCode += "            try {" + _strNewLine;
            strCode += "                return GetListByIP(new List<" + dbTable.ClassName + "IP>() { " + dbTable.ObjectName + "IP }, new List<" + dbTable.ClassName + "DAL.SortOrderType>());" + _strNewLine;
            strCode += "            } catch {" + _strNewLine;
            strCode += "                return null;" + _strNewLine;
            strCode += "            }" + _strNewLine;
            strCode += "        }" + _strNewLine;
            strCode += "   " + _strNewLine;

            strCode += "        public static List<" + dbTable.ClassName + "BO> TryGetListByIP(" + dbTable.ClassName + "IP " + dbTable.ObjectName + "IP, " + dbTable.ClassName + "DAL.SortOrderType sortOrder)" + _strNewLine;
            strCode += "        {" + _strNewLine;
            strCode += "            try {" + _strNewLine;
            strCode += "                return GetListByIP(new List<" + dbTable.ClassName + "IP>() { " + dbTable.ObjectName + "IP }, new List<" + dbTable.ClassName + "DAL.SortOrderType>() { sortOrder });" + _strNewLine;
            strCode += "            } catch {" + _strNewLine;
            strCode += "                return null;" + _strNewLine;
            strCode += "            }" + _strNewLine;
            strCode += "        }" + _strNewLine;
            strCode += "   " + _strNewLine;

            strCode += "        public static List<" + dbTable.ClassName + "BO> TryGetListByIP(" + dbTable.ClassName + "IP " + dbTable.ObjectName + "IP, List<" + dbTable.ClassName + "DAL.SortOrderType> lstSortOrders)" + _strNewLine;
            strCode += "        {" + _strNewLine;
            strCode += "            try {" + _strNewLine;
            strCode += "                return GetListByIP(new List<" + dbTable.ClassName + "IP>() { " + dbTable.ObjectName + "IP }, lstSortOrders);" + _strNewLine;
            strCode += "            } catch {" + _strNewLine;
            strCode += "                return null;" + _strNewLine;
            strCode += "            }" + _strNewLine;
            strCode += "        }" + _strNewLine;
            strCode += "   " + _strNewLine;

            // Add GetListByIP methods that takes a single IP object
            strCode += "        public static List<" + dbTable.ClassName + "BO> GetListByIP(" + dbTable.ClassName + "IP " + dbTable.ObjectName + "IP)" + _strNewLine;
            strCode += "        {" + _strNewLine;
            strCode += "            return " + dbTable.ClassName + "DAL.GetListByIP(new List<" + dbTable.ClassName + "IP>() { " + dbTable.ObjectName + "IP }, new List<" + dbTable.ClassName + "DAL.SortOrderType>());" + _strNewLine;
            strCode += "        }" + _strNewLine;
            strCode += "   " + _strNewLine;

            strCode += "        public static List<" + dbTable.ClassName + "BO> GetListByIP(" + dbTable.ClassName + "IP " + dbTable.ObjectName + "IP, " + dbTable.ClassName + "DAL.SortOrderType sortOrder)" + _strNewLine;
            strCode += "        {" + _strNewLine;
            strCode += "            return " + dbTable.ClassName + "DAL.GetListByIP(new List<" + dbTable.ClassName + "IP>() { " + dbTable.ObjectName + "IP }, new List<" + dbTable.ClassName + "DAL.SortOrderType>() { sortOrder });" + _strNewLine;
            strCode += "        }" + _strNewLine;
            strCode += "   " + _strNewLine;

            strCode += "        public static List<" + dbTable.ClassName + "BO> GetListByIP(" + dbTable.ClassName + "IP " + dbTable.ObjectName + "IP, List<" + dbTable.ClassName + "DAL.SortOrderType> lstSortOrders)" + _strNewLine;
            strCode += "        {" + _strNewLine;
            strCode += "            return " + dbTable.ClassName + "DAL.GetListByIP(new List<" + dbTable.ClassName + "IP>() { " + dbTable.ObjectName + "IP }, lstSortOrders);" + _strNewLine;
            strCode += "        }" + _strNewLine;
            strCode += "   " + _strNewLine;


            // Add GetDataTableByIP methods that takes a single IP object

            strCode += "        public static DataTable GetDataTableByIP(" + dbTable.ClassName + "IP " + dbTable.ObjectName + "IP)" + _strNewLine;
            strCode += "        {" + _strNewLine;
            strCode += "            return " + dbTable.ClassName + "DAL.GetDataTableByIP(new List<" + dbTable.ClassName + "IP>() { " + dbTable.ObjectName + "IP }, new List<" + dbTable.ClassName + "DAL.SortOrderType>());" + _strNewLine;
            strCode += "        }" + _strNewLine;
            strCode += "   " + _strNewLine;

            strCode += "        public static DataTable GetDataTableByIP(" + dbTable.ClassName + "IP " + dbTable.ObjectName + "IP, " + dbTable.ClassName + "DAL.SortOrderType sortOrder)" + _strNewLine;
            strCode += "        {" + _strNewLine;
            strCode += "            return " + dbTable.ClassName + "DAL.GetDataTableByIP(new List<" + dbTable.ClassName + "IP>() { " + dbTable.ObjectName + "IP }, new List<" + dbTable.ClassName + "DAL.SortOrderType>() { sortOrder });" + _strNewLine;
            strCode += "        }" + _strNewLine;
            strCode += "   " + _strNewLine;

            strCode += "        public static DataTable GetDataTableByIP(" + dbTable.ClassName + "IP " + dbTable.ObjectName + "IP, List<" + dbTable.ClassName + "DAL.SortOrderType> lstSortOrders)" + _strNewLine;
            strCode += "        {" + _strNewLine;
            strCode += "            return " + dbTable.ClassName + "DAL.GetDataTableByIP(new List<" + dbTable.ClassName + "IP>() { " + dbTable.ObjectName + "IP }, lstSortOrders);" + _strNewLine;
            strCode += "        }" + _strNewLine;
            strCode += "   " + _strNewLine;


            // Add TryGetListByIP methods that takes a list of IP objects
            strCode += "        public static List<" + dbTable.ClassName + "BO> TryGetListByIP(List<" + dbTable.ClassName + "IP> lst" + dbTable.ClassName + "IP)" + _strNewLine;
            strCode += "        {" + _strNewLine;
            strCode += "            try {" + _strNewLine;
            strCode += "                return GetListByIP(lst" + dbTable.ClassName + "IP, new List<" + dbTable.ClassName + "DAL.SortOrderType>());" + _strNewLine;
            strCode += "            } catch {" + _strNewLine;
            strCode += "                return null;" + _strNewLine;
            strCode += "            }" + _strNewLine;
            strCode += "        }" + _strNewLine;
            strCode += "   " + _strNewLine;

            strCode += "        public static List<" + dbTable.ClassName + "BO> TryGetListByIP(List<" + dbTable.ClassName + "IP> lst" + dbTable.ClassName + "IP, " + dbTable.ClassName + "DAL.SortOrderType sortOrder)" + _strNewLine;
            strCode += "        {" + _strNewLine;
            strCode += "            try {" + _strNewLine;
            strCode += "                return GetListByIP(lst" + dbTable.ClassName + "IP, new List<" + dbTable.ClassName + "DAL.SortOrderType>() { sortOrder });" + _strNewLine;
            strCode += "            } catch {" + _strNewLine;
            strCode += "                return null;" + _strNewLine;
            strCode += "            }" + _strNewLine;
            strCode += "        }" + _strNewLine;
            strCode += "   " + _strNewLine;

            strCode += "        public static List<" + dbTable.ClassName + "BO> TryGetListByIP(List<" + dbTable.ClassName + "IP> lst" + dbTable.ClassName + "IP, List<" + dbTable.ClassName + "DAL.SortOrderType> lstSortOrders)" + _strNewLine;
            strCode += "        {" + _strNewLine;
            strCode += "            try {" + _strNewLine;            
            strCode += "                return GetListByIP(lst" + dbTable.ClassName + "IP, lstSortOrders);" + _strNewLine;
            strCode += "            } catch {" + _strNewLine;
            strCode += "                return null;" + _strNewLine;
            strCode += "            }" + _strNewLine;
            strCode += "        }" + _strNewLine;
            strCode += "   " + _strNewLine;

            strCode += "        public static List<" + dbTable.ClassName + "BO> TryGetListByIP(List<" + dbTable.ClassName + "IP> lst" + dbTable.ClassName + "IP, String sortOrder)" + _strNewLine;
            strCode += "        {" + _strNewLine;
            strCode += "            try {" + _strNewLine; 
            strCode += "                return  GetListByIP(lst" + dbTable.ClassName + "IP, new List<" + dbTable.ClassName + "DAL.SortOrderType>() {(" + dbTable.ClassName + "DAL.SortOrderType) Enum.Parse(typeof (" + dbTable.ClassName + "DAL.SortOrderType), sortOrder, true)});" + _strNewLine;
            strCode += "            } catch {" + _strNewLine;
            strCode += "                return null;" + _strNewLine;
            strCode += "            }" + _strNewLine;
            strCode += "        }" + _strNewLine;
            strCode += "   " + _strNewLine;


            // Add GetListByIP methods that takes a list of IP objects
            strCode += "        public static List<" + dbTable.ClassName + "BO> GetListByIP(List<" + dbTable.ClassName + "IP> lst" + dbTable.ClassName + "IP)" + _strNewLine;
            strCode += "        {" + _strNewLine;
            strCode += "            if (lst" + dbTable.ClassName + "IP.Count == 0) lst" + dbTable.ClassName + "IP.Add(new " + dbTable.ClassName + "IP());" + _strNewLine;
            strCode += "            return " + dbTable.ClassName + "DAL.GetListByIP(lst" + dbTable.ClassName + "IP, new List<" + dbTable.ClassName + "DAL.SortOrderType>());" + _strNewLine;
            strCode += "        }" + _strNewLine;
            strCode += "   " + _strNewLine;

            strCode += "        public static List<" + dbTable.ClassName + "BO> GetListByIP(List<" + dbTable.ClassName + "IP> lst" + dbTable.ClassName + "IP, " + dbTable.ClassName + "DAL.SortOrderType sortOrder)" + _strNewLine;
            strCode += "        {" + _strNewLine;
            strCode += "            if (lst" + dbTable.ClassName + "IP.Count == 0) lst" + dbTable.ClassName + "IP.Add(new " + dbTable.ClassName + "IP());" + _strNewLine;
            strCode += "            return " + dbTable.ClassName + "DAL.GetListByIP(lst" + dbTable.ClassName + "IP, new List<" + dbTable.ClassName + "DAL.SortOrderType>() { sortOrder });" + _strNewLine;
            strCode += "        }" + _strNewLine;
            strCode += "   " + _strNewLine;

            strCode += "        public static List<" + dbTable.ClassName + "BO> GetListByIP(List<" + dbTable.ClassName + "IP> lst" + dbTable.ClassName + "IP, List<" + dbTable.ClassName + "DAL.SortOrderType> lstSortOrders)" + _strNewLine;
            strCode += "        {" + _strNewLine;
            strCode += "            if (lst" + dbTable.ClassName + "IP.Count == 0) lst" + dbTable.ClassName + "IP.Add(new " + dbTable.ClassName + "IP());" + _strNewLine;
            strCode += "            return " + dbTable.ClassName + "DAL.GetListByIP(lst" + dbTable.ClassName + "IP, lstSortOrders);" + _strNewLine;
            strCode += "        }" + _strNewLine;
            strCode += "   " + _strNewLine;

            strCode += "        public static List<" + dbTable.ClassName + "BO> GetListByIP(List<" + dbTable.ClassName + "IP> lst" + dbTable.ClassName + "IP, String sortOrder)" + _strNewLine;
            strCode += "        {" + _strNewLine;
            strCode += "            if (lst" + dbTable.ClassName + "IP.Count == 0) lst" + dbTable.ClassName + "IP.Add(new " + dbTable.ClassName + "IP());" + _strNewLine;
            strCode += "            if (!String.IsNullOrEmpty(sortOrder))" + _strNewLine;
            strCode += "                return " + dbTable.ClassName + "DAL.GetListByIP(lst" + dbTable.ClassName + "IP, new List<" + dbTable.ClassName + "DAL.SortOrderType>() {(" + dbTable.ClassName + "DAL.SortOrderType) Enum.Parse(typeof (" + dbTable.ClassName + "DAL.SortOrderType), sortOrder, true)});" + _strNewLine;
            strCode += "            return " + dbTable.ClassName + "DAL.GetListByIP(lst" + dbTable.ClassName + "IP, new List<" + dbTable.ClassName + "DAL.SortOrderType>());" + _strNewLine;
            strCode += "        }" + _strNewLine;
            strCode += "   " + _strNewLine;

            // Add GetListByIP methods that takes sortOrder as a string
            strCode += "        public static List<" + dbTable.ClassName + "BO> GetListByIP(" + dbTable.ClassName + "IP " + dbTable.ClassName + "IP, String sortOrder)" + _strNewLine;
            strCode += "        {" + _strNewLine;
            strCode += "            if (!String.IsNullOrEmpty(sortOrder))" + _strNewLine;
            strCode += "                return " + dbTable.ClassName + "DAL.GetListByIP(new List<" + dbTable.ClassName + "IP>() { " + dbTable.ClassName + "IP }, new List<" + dbTable.ClassName + "DAL.SortOrderType>() { (" + dbTable.ClassName + "DAL.SortOrderType)Enum.Parse(typeof(" + dbTable.ClassName + "DAL.SortOrderType), sortOrder, true) });" + _strNewLine;
            strCode += "            return " + dbTable.ClassName + "DAL.GetListByIP(new List<" + dbTable.ClassName + "IP>() { " + dbTable.ClassName + "IP }, new List<" + dbTable.ClassName + "DAL.SortOrderType>());" + _strNewLine;
            strCode += "        }" + _strNewLine;
            strCode += "   " + _strNewLine;

            strCode += "        public static List<" + dbTable.ClassName + "BO> GetListByIP(" + dbTable.ClassName + "IP " + dbTable.ClassName + "IP, List<String> lstSortOrders)" + _strNewLine;
            strCode += "        {" + _strNewLine;
            strCode += "            List<" + dbTable.ClassName + "DAL.SortOrderType> lstSortOrderType = new List<" + dbTable.ClassName + "DAL.SortOrderType>();" + _strNewLine;
            strCode += "            foreach (String sortOrder in lstSortOrders)" + _strNewLine;
            strCode += "                if (sortOrder != \"\")" + _strNewLine;
            strCode += "                    lstSortOrderType.Add((" + dbTable.ClassName + "DAL.SortOrderType)Enum.Parse(typeof(" + dbTable.ClassName + "DAL.SortOrderType), sortOrder, true));" + _strNewLine;
            strCode += "            if (lstSortOrderType.Count > 0)" + _strNewLine;
            strCode += "                return " + dbTable.ClassName + "DAL.GetListByIP(new List<" + dbTable.ClassName + "IP>() { " + dbTable.ClassName + "IP }, lstSortOrderType);" + _strNewLine;
            strCode += "            return " + dbTable.ClassName + "DAL.GetListByIP(new List<" + dbTable.ClassName + "IP>() { " + dbTable.ClassName + "IP }, new List<" + dbTable.ClassName + "DAL.SortOrderType>());" + _strNewLine;
            strCode += "        }" + _strNewLine;
            strCode += "   " + _strNewLine;

            strCode += "        public static List<" + dbTable.ClassName + "BO> GetListByIP(List<" + dbTable.ClassName + "IP> lst" + dbTable.ClassName + "IP, List<String> lstSortOrders)" + _strNewLine;
            strCode += "        {" + _strNewLine;
            strCode += "            if (lst" + dbTable.ClassName + "IP.Count == 0) lst" + dbTable.ClassName + "IP.Add(new " + dbTable.ClassName + "IP());" + _strNewLine;
            strCode += "            List<" + dbTable.ClassName + "DAL.SortOrderType> lstSortOrderType = new List<" + dbTable.ClassName + "DAL.SortOrderType>();" + _strNewLine;
            strCode += "            foreach (String sortOrder in lstSortOrders)" + _strNewLine;
            strCode += "                if (sortOrder != \"\")" + _strNewLine;
            strCode += "                    lstSortOrderType.Add((" + dbTable.ClassName + "DAL.SortOrderType)Enum.Parse(typeof(" + dbTable.ClassName + "DAL.SortOrderType), sortOrder, true));" + _strNewLine;
            strCode += "            if (lstSortOrderType.Count > 0)" + _strNewLine;
            strCode += "                return " + dbTable.ClassName + "DAL.GetListByIP(lst" + dbTable.ClassName + "IP, lstSortOrderType);" + _strNewLine;
            strCode += "            return " + dbTable.ClassName + "DAL.GetListByIP(lst" + dbTable.ClassName + "IP, new List<" + dbTable.ClassName + "DAL.SortOrderType>());" + _strNewLine;
            strCode += "        }" + _strNewLine;

            #endregion

            if (_generateInnerJoinCode)
            {
                #region AddGetListByInnerJoinsMethods

                // Add GetListByIP Method that allows inner joins
                int intFK = 0;
                dbCommand = db.GetSqlStringCommand("exec sp_fkeys @pktable_name = '" + dbTable.TableName + "'");
                intFK = intFK + db.ExecuteDataSet(dbCommand).Tables[0].Rows.Count;

                dbCommand = db.GetSqlStringCommand("exec sp_fkeys @fktable_name = '" + dbTable.TableName + "'");
                intFK = intFK + db.ExecuteDataSet(dbCommand).Tables[0].Rows.Count;

                if (intFK > 0)
                {
                    strCode += "        public static DataTable GetListByIP(Dictionary<Object, Object> lstInnerJoinWithIP, List<String> lstOrderBy)" + _strNewLine;
                    strCode += "        {" + _strNewLine;
                    strCode += "            return " + dbTable.ClassName + "DAL.GetListByIP(new List<" + dbTable.ClassName + "IP>(), lstInnerJoinWithIP, lstOrderBy);" + _strNewLine;
                    strCode += "        }" + _strNewLine;
                    strCode += "   " + _strNewLine;

                    strCode += "        public static DataTable GetListByIP(List<" + dbTable.ClassName + "IP> lst" + dbTable.ClassName + "IP, Dictionary<Object, Object> lstInnerJoinWithIP, List<String> lstOrderBy)" + _strNewLine;
                    strCode += "        {" + _strNewLine;
                    strCode += "            if (lst" + dbTable.ClassName + "IP.Count == 0) lst" + dbTable.ClassName + "IP.Add(new " + dbTable.ClassName + "IP());" + _strNewLine;
                    strCode += "            return " + dbTable.ClassName + "DAL.GetListByIP(lst" + dbTable.ClassName + "IP, lstInnerJoinWithIP, lstOrderBy);" + _strNewLine;
                    strCode += "        }" + _strNewLine;
                    strCode += "   " + _strNewLine;

                    strCode += "        public static DataTable GetListByIP(" + dbTable.ClassName + "IP " + dbTable.ClassName + "IP, String sortOrder, Object join)" + _strNewLine;
                    strCode += "        {" + _strNewLine;
                    strCode += "            Dictionary<Object, Object> dictionary = new Dictionary<Object, Object>();" + _strNewLine;
                    strCode += "            dictionary.Add(join, " + dbTable.ClassName + "IP);" + _strNewLine;
                    strCode += "            return " + dbTable.ClassName + "DAL.GetListByIP(new List<" + dbTable.ClassName + "IP>(), dictionary, new List<String>() { sortOrder });" + _strNewLine;
                    strCode += "        }" + _strNewLine;
                    strCode += "   " + _strNewLine;

                    strCode += "        public static DataTable GetListByIP(List<" + dbTable.ClassName + "IP> lst" + dbTable.ClassName + "IP," + dbTable.ClassName + "IP " + dbTable.ClassName + "IP, String sortOrder, Object join)" + _strNewLine;
                    strCode += "        {" + _strNewLine;
                    strCode += "            if (lst" + dbTable.ClassName + "IP.Count == 0) lst" + dbTable.ClassName + "IP.Add(new " + dbTable.ClassName + "IP());" + _strNewLine;
                    strCode += "            Dictionary<Object, Object> dictionary = new Dictionary<Object, Object>();" + _strNewLine;
                    strCode += "            dictionary.Add(join, " + dbTable.ClassName + "IP);" + _strNewLine;
                    strCode += "            return " + dbTable.ClassName + "DAL.GetListByIP(lst" + dbTable.ClassName + "IP, dictionary, new List<String>() { sortOrder });" + _strNewLine;
                    strCode += "        }" + _strNewLine;
                }

                #endregion
            }

            // Save and delete methods is not allowed on enum tables
            if (!strTableName.EndsWith("Enum"))
            {
                // Add Delete mehtods
                if (dbTable.DbColumns.Exists(column => column.ColumnName == "Deleted"))
                {
                    // Delete using flagg
                    strCode += "   " + _strNewLine;
                    strCode += "        /// <summary>" + _strNewLine;
                    strCode += "        /// Performs an UPDATE query and set the DELETED flag to false" + _strNewLine;
                    strCode += "        /// </summary>" + _strNewLine;
                    strCode += "        public static void Delete(" + dbTable.ClassName + "BO " + dbTable.ObjectName + "BO)" + _strNewLine;
                    strCode += "        {" + _strNewLine;
                    strCode += "            " + dbTable.ClassName + "DAL.Delete(" + dbTable.ObjectName + "BO);" + _strNewLine;
                    strCode += "            " + dbTable.ObjectName + "BO.Deleted = true;" + _strNewLine;
                    strCode += "        }" + _strNewLine;
                    strCode += "   " + _strNewLine;

                    // Delete from database
                    strCode += "        /// <summary>" + _strNewLine;
                    strCode += "        /// If deleteFromDatabase is set to true then perform a DELETE query and set the object parameter to null" + _strNewLine;
                    strCode += "        /// else perform an UPDATE query and set the Delted flag to false" + _strNewLine;
                    strCode += "        /// </summary>" + _strNewLine;
                    strCode += "        public static void Delete(" + dbTable.ClassName + "BO " + dbTable.ObjectName + "BO, bool deleteFromDatabase)" + _strNewLine;
                    strCode += "        {" + _strNewLine;
                    strCode += "            if(deleteFromDatabase)" + _strNewLine;
                    strCode += "            {" + _strNewLine;
                    strCode += "                " + dbTable.ClassName + "DAL.DeleteFromDatabase(" + dbTable.ObjectName + "BO);" + _strNewLine;
                    strCode += "                " + dbTable.ObjectName + "BO = null;" +_strNewLine;
                    strCode += "            }" + _strNewLine;
                    strCode += "            else" + _strNewLine;
                    strCode += "                Delete(" + dbTable.ObjectName + "BO);" + _strNewLine;
                    strCode += "        }" + _strNewLine;
                    strCode += "   " + _strNewLine;
                }
                else
                {
                    strCode += "   " + _strNewLine;
                    strCode += "        /// <summary>" + _strNewLine;
                    strCode += "        /// Note! The object doesn't have the Deleted flag in the database and will therefore be removed completely from the database." + _strNewLine;
                    strCode += "        /// </summary>" + _strNewLine;
                    strCode += "        /// <param name=\"regulationReplaceBO\"></param>" + _strNewLine;
                    strCode += "        public static void Delete(" + dbTable.ClassName + "BO " + dbTable.ObjectName + "BO)" + _strNewLine;
                    strCode += "        {" + _strNewLine;
                    strCode += "            " + dbTable.ClassName + "DAL.DeleteFromDatabase(" + dbTable.ObjectName + "BO);" + _strNewLine;
                    strCode += "            " + dbTable.ObjectName + "BO = null;" +_strNewLine;
                    strCode += "        }" + _strNewLine;
                    strCode += "   " + _strNewLine;

                    strCode += "        [Obsolete(\"This method is deprecated, please use Delete instead.\")]" + _strNewLine;
                    strCode += "        public static void DeleteFromDatabase(" + dbTable.ClassName + "BO " + dbTable.ObjectName + "BO)" + _strNewLine;
                    strCode += "        {" + _strNewLine;
                    strCode += "            Delete(" + dbTable.ObjectName + "BO);" + _strNewLine;
                    strCode += "        }" + _strNewLine;
                    strCode += "   " + _strNewLine;
                }

                // Add Save mehtods
                strCode += "        public static void Save(" + dbTable.ClassName + "BO " + dbTable.ObjectName + "BO)" + _strNewLine;
                strCode += "        {" + _strNewLine;
               
                if(_generateDryLog)
                    strCode += "            Save(" + dbTable.ObjectName + "BO, ConfigurationManager.AppSettings[\"DRY_LogUpdateChanges\"] != null && ConfigurationManager.AppSettings[\"DRY_LogUpdateChanges\"] == \"true\");" + _strNewLine;
                else
                    strCode += "            Save(" + dbTable.ObjectName + "BO, false);" + _strNewLine;
                    
                strCode += "        }" + _strNewLine;
                strCode += "   " + _strNewLine;


                if (_generateDryLog)
                {
                    strCode += "        public static void Save(" + dbTable.ClassName + "BO " + dbTable.ObjectName + "BO, bool blnLogChangeOnUpdate)" + _strNewLine;
                    strCode += "        {" + _strNewLine;
                    strCode += "            Save(" + dbTable.ObjectName + "BO, blnLogChangeOnUpdate, false);" + _strNewLine;
                    strCode += "        }" + _strNewLine;
                    strCode += "   " + _strNewLine;
                }
                
                

                strCode += "        /// <summary>" + _strNewLine;
                strCode += "        /// Either performs an UPDATE or INSERT query depending on whether the identity of the object is set or not, the blnSaveWithIdentity parameter allows the insert to save the identity by" + _strNewLine;
                strCode += "        /// turning IDENTITY_INSERT on during the save." + _strNewLine;
                strCode += "        /// </summary>" + _strNewLine;

                if (_generateDryLog)
                {
                    strCode += "        public static void Save(" + dbTable.ClassName + "BO " + dbTable.ObjectName + "BO, bool blnLogChangeOnUpdate, bool blnSaveWithIdentity)" + _strNewLine;
                }
                else
                {
                    strCode += "        public static void Save(" + dbTable.ClassName + "BO " + dbTable.ObjectName + "BO, bool blnSaveWithIdentity)" + _strNewLine;
                }
                strCode += "        {" + _strNewLine;
                strCode += "            if(" + dbTable.ObjectName + "BO." + dbTable.ClassName + "Id > 0  && !blnSaveWithIdentity)" + _strNewLine;
                strCode += "            {" + _strNewLine;
                if (_generateDryLog)
                {
                    strCode += "               if(blnLogChangeOnUpdate)" + _strNewLine;
                    strCode += "                  LogChange(" + dbTable.ObjectName + "BO);" + _strNewLine;
                }
                strCode += "               " + dbTable.ClassName + "DAL.Update(" + dbTable.ObjectName + "BO);" + _strNewLine;
                strCode += "            }" + _strNewLine;
                strCode += "            else" + _strNewLine;
                strCode += "            {" + _strNewLine;
                strCode += "                 if(blnSaveWithIdentity)" + _strNewLine;
                strCode += "                      " + dbTable.ClassName + "DAL.Insert(" + dbTable.ObjectName + "BO, true);" + _strNewLine;
                strCode += "                 else" + _strNewLine;
                strCode += "                      " + dbTable.ClassName + "DAL.Insert(" + dbTable.ObjectName + "BO);" + _strNewLine;
                strCode += "            }" + _strNewLine;
                strCode += "        }" + _strNewLine;

                if(_generateDryLog)
                    AddLogMethod(ref strCode, dbTable);
            }

            AddJoinEnums(ref strCode, strTableName);

            strCode += "    }" + _strNewLine;
            strCode += "}" + _strNewLine;

            return strCode;
        }

        protected static void AddJoinEnums(ref string strCode, string strTableName)
        {
            string strJoin = AddJoinEnum(strTableName);
            if (strJoin != "")
            {
                strCode += "        public enum InnerJoinEnum" + _strNewLine;
                strCode += "        {" + _strNewLine;
                strCode += strJoin;
                strCode = strCode.Substring(0, strCode.Length - 4) + _strNewLine;
                strCode += "        }" + _strNewLine;
                strCode += @"" + _strNewLine;
            }


            strJoin = AddJoinEnum(strTableName);
            if (strJoin != "")
            {
                strCode += "        public enum LeftJoinEnum" + _strNewLine;
                strCode += "        {" + _strNewLine;
                strCode += strJoin;
                strCode = strCode.Substring(0, strCode.Length - 4) + _strNewLine;
                strCode += "        }" + _strNewLine;
                strCode += @"" + _strNewLine;
            }


            strJoin = AddJoinEnum(strTableName);
            if (strJoin != "")
            {
                strCode += "        public enum RightJoinEnum" + _strNewLine;
                strCode += "        {" + _strNewLine;
                strCode += strJoin;
                strCode = strCode.Substring(0, strCode.Length - 4) + _strNewLine;
                strCode += "        }" + _strNewLine;
                strCode += @"" + _strNewLine;
            }
        }

        private static string AddJoinEnum(string strTableName)
        {
            string strCode = "";

            foreach (DataRow dataRow in GetRelationTable(strTableName, false).Rows)
                strCode += "            " + GetEnumNameFromRelationTable(dataRow, strTableName) + ", " + _strNewLine;

            return strCode;
        }

        protected static DataTable GetRelationTable(string strTableName, bool distinct)
        {
            // Get table relations
            Database db = GetDatabase();
            DbCommand dbCommand = db.GetSqlStringCommand("exec sp_fkeys @pktable_name = '" + strTableName + "'");

            string[] columnNameFk = new[] { "PKTABLE_NAME", "FKCOLUMN_NAME", "PKCOLUMN_NAME" };
            string[] columnNamePk = new[] { "FKTABLE_NAME", "FKCOLUMN_NAME", "PKCOLUMN_NAME" };
            string[] columnNameFinal = new[] { "TABLE", "COLUMN", "PKCOLUMN" };

            DataTable dataTablePk = db.ExecuteDataSet(dbCommand).Tables[0].DefaultView.ToTable(distinct, columnNamePk);
            dataTablePk.Columns[0].ColumnName = "TABLE";
            dataTablePk.Columns[1].ColumnName = "COLUMN";
            dataTablePk.Columns[2].ColumnName = "PKCOLUMN";

            dbCommand = db.GetSqlStringCommand("exec sp_fkeys @fktable_name = '" + strTableName + "'");

            DataTable dataTableFk = db.ExecuteDataSet(dbCommand).Tables[0].DefaultView.ToTable(distinct, columnNameFk);
            dataTableFk.Columns[0].ColumnName = "TABLE";
            dataTableFk.Columns[1].ColumnName = "COLUMN";
            dataTableFk.Columns[2].ColumnName = "PKCOLUMN";

            dataTableFk.Merge(dataTablePk);
            DataTable dataTableFinal = dataTableFk.DefaultView.ToTable(true, columnNameFinal);

            return dataTableFinal;
        }

        protected static string GetEnumNameFromRelationTable(DataRow dataRow, string strTableName)
        {

            string strTable = (strTableName.TrimStart(_tablePrefix.ToCharArray()) + "Id");
            string strRelationTable = dataRow["TABLE"].ToString().TrimStart(_tablePrefix.ToCharArray());
            string strRelationColumn = dataRow["COLUMN"].ToString();
            string strReurn = "";

            try
            {
                strReurn = strRelationTable + "_" + (strRelationColumn.Contains(strTable) ? strRelationColumn.Substring(0, strRelationColumn.IndexOf(strTable)) : strRelationColumn.Substring(0, strRelationColumn.IndexOf("Id")));
            }
            catch (Exception)
            {
                throw new Exception("Invalid relation table identification exception: Check that relation table (" + strRelationColumn + ") primary key ends with \"Id\".");
            }

            if (strReurn.EndsWith("_"))
                strReurn = strReurn.Substring(0, strReurn.Length - 1);

            return strReurn;
        }

        private static void AddLogMethod(ref string strCode, DbTable dbTable)
        {
            strCode += "    " + _strNewLine;
            strCode += "        private static void LogChange(" + dbTable.ClassName + "BO new" + dbTable.ClassName + ")" + _strNewLine;
            strCode += "        {" + _strNewLine;
            strCode += "            string log = \"\";" + _strNewLine;
            strCode += "            " + dbTable.ClassName + "BO old" + dbTable.ClassName + " = " + dbTable.ClassName + "DAL.GetById(new" + dbTable.ClassName + "." + dbTable.ClassName + "Id);" + _strNewLine;
            strCode += "    " + _strNewLine;

            foreach (DbColumn dbColumn in dbTable.DbColumns)
            {
                if (!dbColumn.IsPK && dbColumn.ColumnName != "Created")
                {
                    strCode += "            if(old" + dbTable.ClassName + "." + dbColumn.ColumnName + " != new" + dbTable.ClassName + "." + dbColumn.ColumnName + ")" + _strNewLine;
                    strCode += "                log += \"" + dbColumn.ColumnName + ": \" + old" + dbTable.ClassName + "." + dbColumn.ColumnName + " + \" -> \" + new" + dbTable.ClassName + "." + dbColumn.ColumnName + " + \". \";" + _strNewLine;
                    strCode += "     " + _strNewLine; 
                }
            }

            strCode += "            if(log != \"\")" + _strNewLine;
            strCode += "                DryLogBLL.Save(new DryLogBO(){ObjectName=\"" + dbTable.ClassName + "\", ObjectId=new" + dbTable.ClassName + "." + dbTable.ClassName + "Id, LogMessage=log});" + _strNewLine;

            strCode += "        }" + _strNewLine;
        }
    }
}


